#![allow(unused_varibles)]
type File = String;
fn main() {
    greet_world();
    println!("-------------------------");
    test();
    println!("-------------------------");
    variables();
    println!("-------------------------");
    varTypes();
    println!("-------------------------");
    owner();
    println!("-------------------------");
    let mut f1 = File::from("f1.txt");
    open(&mut f1);
    //read(&mut f1, &mut vec![]);
    close(&mut f1);
    println!("-------------------------");
    testString();
    println!("-------------------------");
    testTup();
    println!("-------------------------");
    testStruct();
}

fn greet_world()
{
    let southern_germany = "Grüß Gott!";
    let chinese = "世界，你好";
    let english = "World, hello";
    let regions = [southern_germany, chinese, english];
    for region in regions.iter() {
        println!("{}", &region);
    }
}

fn test()
{
    let  penguin_data = "\
        common name,length (cm)
       Little penguin,33
       Yellow-eyed penguin,65
       Fiordland penguin,60
       Invalid,data
    ";
    let records = penguin_data.lines();
    for(i,record) in records.enumerate(){
        if i == 0 || record.trim().len() == 0{
            continue;
        }
        let fields:Vec<_> = record
            .split(',')
            .map(|field| field.trim())
            .collect();
        if cfg!(debug_assertions) {
            // 输出到标准错误输出
            eprintln!("debug: {:?} -> {:?}",
                      record, fields);
        }
        let name = fields[0];
        // 1. 尝试把 fields[1] 的值转换为 f32 类型的浮点数，如果成功，则把 f32 值赋给 length 变量
        //
        // 2. if let 是一个匹配表达式，用来从=右边的结果中，匹配出 length 的值：
        //   1）当=右边的表达式执行成功，则会返回一个 Ok(f32) 的类型，若失败，则会返回一个 Err(e) 类型，if let 的作用就是仅匹配 Ok 也就是成功的情况，如果是错误，就直接忽略
        //   2）同时 if let 还会做一次解构匹配，通过 Ok(length) 去匹配右边的 Ok(f32)，最终把相应的 f32 值赋给 length
        //
        // 3. 当然你也可以忽略成功的情况，用 if let Err(e) = fields[1].parse::<f32>() {...}匹配出错误，然后打印出来，但是没啥卵用
        if let Ok(length) = fields[1].parse::<f32>() {
            // 输出到标准输出
            println!("{}, {}cm", name, length);
        }
    }

}

//变量
fn variables()
{
    let mut x = 8;
    println!("The value of x is :{}",x);
    x = 6;
    println!("The value of x is :{}",x);
    let _y = 10;
    //解构
    let (a,mut b) :(bool,bool) = (true,false);
    println!("a = {:?},b = {:?}",a,b);
    b = true;
    assert_eq!(a,b);

    /*常量 不允许使用mut 使用const 修饰符 必须标明类型*/
    const MAX_POINTS:u32 = 100_000;
}

/* 数据类型*/
fn varTypes()
{
    let guess:i32 = "42".parse().expect("Not a number!");
    println!("guess : {}",guess);
    //整数
    /**
     使用 wrapping_* 方法在所有模式下都按照补码循环溢出规则处理，例如 wrapping_add
    如果使用 checked_* 方法时发生溢出，则返回 None 值
    使用 overflowing_* 方法返回该值和一个指示是否存在溢出的布尔值
    使用 saturating_* 方法，可以限定计算后的结果不超过目标类型的最大值或低于最小值，例如

     */
    let a :u8 = 255;
    let b = a.wrapping_add(20);
    println!("{}",b);

    //浮点数
    let _x =2.0; //f64
    let _y:f32  = 3.0;

    //字符
    let _x8 = '中';
    println!("字符'中'占用了{}字节的内存大小",std::mem::size_of_val(&_x8));

    //布尔
    let t = true;
    let f:bool  = false;

    if f {
        eprintln!("这是段无意义的代码");
    }


    //块语句
    let y0 = {
        let x = 3;
        x + 1
    };

    println!("The value of y is: {}", y0);

}

/*函数*/
fn add_two(i:i32,j:i32) -> i32{
    i + j
}

/*所有权*/
fn owner()
{
    let x:&str = "hello world";
    let y = x;
    println!("{},{}",x,y);
}


/*文件所有权*/
fn open(f:&mut File) -> bool{
    true
}

fn close(f:&mut File) -> bool{
    true
}


#[allow(dead_code)]
fn read(f:&mut File,save_to:&mut Vec<u8>) -> !{
    unimplemented!()
}



/*字符串与切片*/
fn testString()
{
    let s = String::from("hello world");
    say_hello(&s);
    say_hello(&s[..]);
    say_hello(s.as_str());

    let mut s1 = String::from("hello");
    s1.push_str("rust");
    println!("追加字符串: push_str() -> {}",s1);
    s1.push('!');
    println!("追加字符 push() ->{}",s1);
}

fn say_hello(s:&str)
{
    println!("{}",s)
}

/*元组*/
fn testTup()
{
    let tup = (500,6.4,1);
    let (x,y,z) = tup;

    println!("The value of y is: {}",y);

    let s1 = String::from("hello");
    let (s2,len) = calculate_length(s1);
    println!("The length of '{}' is {}",s2,len);
}
fn calculate_length(s:String) -> (String,usize)
{
    let length = s.len();
    (s,length)
}

/*结构体*/
#[derive(Debug)]
struct User{
    active:bool,
    username:String,
    email:String,
    sign_in_count:u64
}

fn testStruct()
{
    let mut user1 = User{
        email: String::from("someone@example.com"),
        username: String::from("someusername123"),
        active: true,
        sign_in_count: 1,
    };

    user1.email = String::from("ssssss");

    let user2 = User {
        email:String::from("wsdasda"),
        ..user1
    };

    println!("user is {:?}",user2);
    println!("user is {:#?}",user2);
    dbg!(&user2);
}